﻿using System;
using System.Linq;
using System.Windows.Forms;
using CommonLibrary;
using CommonLibrary.Models.Profiles;
using InputManager.AdvOperation;

namespace InputManager.InputHandlers
{
    public enum InputType
    {
        KeyDown,
        KeyUp,
        MouseDown,
        MouseUp,
        MouseMove,
        MouseWheel
    }

    public class CalibrationProcessor
    {
        private readonly CalibrationTools _calibrationTools;
        private readonly IAppContext _context;
        
        public CalibrationProcessor(IAppContext context)
        {
            _context = context;
            _calibrationTools = new CalibrationTools(context);
        }
        
        public bool ValidateInput(InputType inputType, object inputData)
        {
            switch (inputType)
            {
                // Todo add suport for key up
                case InputType.KeyDown:
                    return ProcessKey(inputData);
                case InputType.MouseDown:
                    return ProcessMouseButton(inputData);
                case InputType.MouseMove:
                    return ProcessMouseMove(inputData);
                case InputType.MouseWheel:
                    return ProcessMouseWheel(inputData);
            }
            return false;
        }

        private bool ProcessMouseMove(object inputData)
        {
            return _context.GeneralInfo.IsConfigurationModeActive;
        }

        private bool ProcessMouseWheel(object inputData)
        {
            return _context.GeneralInfo.IsConfigurationModeActive;
        }

        private bool ProcessMouseButton(object inputData)
        {
            return _context.GeneralInfo.IsConfigurationModeActive;
        }

        /// <summary>
        /// F3  - start circle
        /// F4  - Save Values
        /// 
        /// F5  - Liniar Auto increase
        /// F6  - Liniar Auto decrease 
        /// F7  - Increase dead zone for X and Y axis
        /// F8  - Decrease dead zone for X and Y axis
        /// 
        /// F9   - Increase dead zone for X 
        /// F10  - Decrease dead zone for X 
        /// F11  - Increase dead zone for Y 
        /// F12  - Decrease dead zone for Y 
        /// 
        /// All of the operations are done on a independant thread
        /// </summary>
        private bool ProcessKey(object inputData)
        {
            var key = Enum.ToObject(typeof (Keys), inputData);
            var action = _context.ProcessedProfile.ConfigAction.FirstOrDefault(d => d.Key.Equals(key.ToString())).Value;
            if (action == null) return false;

            return ExecuteSpecialAction(action);
        }

        private bool ExecuteSpecialAction(SepcialAction action)
        {
            if(CheckCalibrationMode(action.ActionName)) return true;
            if (!_context.GeneralInfo.IsConfigurationModeActive) return false;

            // TODO Bad practice but too lazy to improve upon now
            switch (action.ActionName)
            {
                case "IncrementAxisMultiplier":
                    var specialaction1 = _context.ProfileConfig.AxisAction.FirstOrDefault(a => a.Key.Equals(action.Target)).Value;
                    if (specialaction1 == null) return false;
                    specialaction1.Multiplier += (double) action.Parameter;
                    break;
                case "IncrementAxisExponent":
                    var specialaction2 = _context.ProfileConfig.AxisAction.FirstOrDefault(a => a.Key.Equals(action.Target)).Value;
                    if (specialaction2 == null) return false;
                    specialaction2.Exponent += (double) action.Parameter;
                    break;
                case "IncrementAxisDeadZone":
                    var specialaction3 = _context.ProfileConfig.AxisAction.FirstOrDefault(a => a.Key.Equals(action.Target)).Value;
                    if (specialaction3 == null) return false;
                    specialaction3.DeadZone += (double)action.Parameter;
                    break;
                case "CalibrationCircle":
                    // TODO add support for both sticks
                    _calibrationTools.CalibrationCircle();
                    break;
                case "ChangeCalibrationCircleType":
                    _calibrationTools.ChangeCircleType(action.Target.ToString());
                    break;
                case "AutoIncreaseCircle":
                    if (action.Target.ToString().Equals("Up")) _calibrationTools.AutoIncreaseCircle();
                    else if (action.Target.ToString().Equals("Down")) _calibrationTools.AutoDecreaseCircle();
                    break;
                case "ManualIncreaseCircle":
                    if (action.Target.ToString().Equals("Up")) _calibrationTools.IncreaseCircle();
                    else if (action.Target.ToString().Equals("Down")) _calibrationTools.DecreaseCircle();
                    break;
            }

            return true;
        }

        private bool CheckCalibrationMode(string actionName)
        {
            if(actionName.Equals("CalibrationMode"))
            {
                if (_context.GeneralInfo.IsConfigurationModeActive) _calibrationTools.StopCalibrationCircle();
                _context.GeneralInfo.IsConfigurationModeActive = !_context.GeneralInfo.IsConfigurationModeActive;
                return true;
            }

            return false;
        }
    }
}
